<?php
class Deal extends AppModel {

	var $name = 'Deal';
	const DISCOUNT_TYPE_FLAT = 0;
	const DISCOUNT_TYPE_PERCENT = 1;
	const PUBLISH = 1;
	const UNPUBLISH = 0;
	const PURCHASE_LINK_ON = 1;
	const PURCHASE_LINK_OFF = 0;
	
	var $order = array('Deal.publish_on_date'=>'DESC','Deal.publish_on_time'=>'DESC','Deal.created'=>'DESC');

	var $validate = array(
		'title' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required"
				)
		),
		'listing_id' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required"
				)
		),
		'list_category_id' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required"
				)
		),
		'regular_price' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required"
				),
				'validNumber'=>array(
						'rule' => 'numeric',
						'message' => "Invalid value",
						'required' => false,
						'allowEmpty' => true
				),
				'notLessThanZeroCheck'=>array(
						'rule' => array('comparison','>=',0),
						'message' => "Entered value should be greater than or equal to zero",
						'required' => false,
						'allowEmpty' => true
				)
		),
		'discount_type' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required"
				)
		),
		'discount' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required"
				),
				'validNumber'=>array(
						'rule' => 'numeric',
						'message' => "Invalid value",
						'required' => false,
						'allowEmpty' => true
				),
				'validPercent'=>array(
						'rule' => array('isValidPercentage'),
						'message' => "Invalid percentage value",
						'required' => false,
						'allowEmpty' => true
				),
				'notLessThanZeroCheck'=>array(
						'rule' => array('comparison','>=',0),
						'message' => "Entered value should be greater than or equal to zero",
						'required' => false,
						'allowEmpty' => true
				)
		),
		'total_quantity' => array(
				/*
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required"
				),
				*/
				'validNumber'=>array(
						'rule' => '/^\d+$/',
						'message' => "Invalid value",
						'required' => false,
						'allowEmpty' => true
				)
		),
		'expires' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required"
				),
				'validDate'=>array(
						'rule' => 'date',
						'message' => "Invalid date",
						'required' => false,
						'allowEmpty' => true
				),
				/*
				'futureDate'=>array(
						'rule'=>array('isFutureDate','expires'),
						'message'=>'Entered date should be a future date',
						'allowEmpty' => true,
						'required' => false
				),
				*/
				'publishDateCheck'=>array(
						'rule'=>array('isOlderThanPublishDateCheck'),
						'message'=>'Entered date should be later than the date of publishing',
						'allowEmpty' => true,
						'required' => false
				)
		),
		/*
		'purchase_link_status' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required",
				)
		),
		*/
		'publish_on_date' => array(
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required",
				),
				'validDate'=>array(
						'rule' => 'date',
						'message' => "Invalid date",
						'required' => false,
						'allowEmpty' => true
				),
				'futureDate'=>array(
						'rule'=>array('isValidPublishDateTime'),
						'message'=>'Entered date/time should be a future date/time',
						'allowEmpty' => true,
						'required' => false,
						//'on' => 'create'
				),
		),
		'publish_on_time' => array(
				/*
				'notempty'=>array(
						'rule' => VALID_NOT_EMPTY,
						'message' => "This field is required",
				),
				*/
				'validTime'=>array(
						'rule' => 'time',
						'message' => "Invalid time",
						'required' => false,
						'allowEmpty' => true
				),
				'futureTime'=>array(
						'rule'=>array('isValidPublishDateTime'),
						'message'=>'Entered date/time should be a future date/time',
						'allowEmpty' => true,
						'required' => false,
						//'on' => 'create'
				),
		)
	);

	//The Associations below have been created with all possible keys, those that are not needed can be removed
	var $belongsTo = array(
		'Listing' => array(
			'className' => 'Listing',
			'foreignKey' => 'listing_id',
			'conditions' => '',
			'fields' => '',
			'order' => ''
		),
		'ListCategory' => array(
			'className' => 'ListCategory',
			'foreignKey' => 'list_category_id',
			'conditions' => '',
			'fields' => '',
			'order' => ''
		)
	);
	
	var $hasMany = array(
			'DealAsset'=>array(
					'className'=>'Deals.DealAsset',
					'foreignKey'=>'deal_id',
					'dependent'=>true,
			)
	);
	
	var $fieldProperties = array(
			'title'=>array(
					'label'=>'Title',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"text",
			),
			'list_category_id' => array(
					'label'=>'Category',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"select",
					'options'=>array()
			),
			'regular_price' => array(
					'label'=>'Regular price',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"text",
			),
			'discount_type' => array(
					'label'=>'Discount type',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"select",
					'options' => array()
			),
			'discount' => array(
					'label'=>'Discount',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"text",
			),
			'total_quantity' => array(
					'label'=>'Total deals',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"text",
					'after'=>'Empty or 0 for no limit'
			),
			'publish_on_date' => array(
					'label'=>'Publish on date',
					'group'=>array('add','edit','view'),
					'type'=>"datePicker",
			),
			'publish_on_time' => array(
					'label'=>'Publish on time',
					'group'=>array('add','edit','view'),
					'type'=>"time",
					'timeFormat'=>24
			),
			'expires' => array(
					'label'=>'Will expire on',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"datePicker",
			),
			/*
			'purchase_link_status' => array(
					'label'=>'Can be purchased Online',
					'type'=>"select",
					'group'=>array('add','view'),
					'options'=>array()
			),
			*/
			'description' => array(
					'label'=>'Highlights',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"textarea", //'type'=>"editor",
			),
			'fine_print' => array(
					'label'=>'Fine print',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"textarea", //'type'=>"editor",
			),
			'validity' => array(
					'label'=>'Validity',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"textarea", //'type'=>"editor",
			),
			'terms' => array(
					'label'=>'Terms and conditions (optional)',
					'group'=>array('add','edit','view','edit_published'),
					'type'=>"textarea", //'type'=>"editor",
			),
			'asset_inputs' => array(
					'type'=>"parent",
					'childInfo' => array(
							'model'=>"Deals.DealAsset",
							'allowEdit' => false,
							'child_group' => "add",
							'allowMultiple' => true,
							'deleteMissing' => false,
					),
					'fieldset' => false,
			)
	);
	
	var $actsAs = array(
			'Assets.MultiUpload' => array(
					"type"=>"hasMany",
					"uploadModelName"=>"Deals.DealAsset"
			),
	);
	
	var $additionalFields = array(
			'uploadedFile',
			'image',
			'viewUrl',
			'finalPrice',
			'deal_status'
	);
	
	//var $cacheFields = array();
	
	function beforeSave($options = array())
	{
		if(isset($this->data[$this->alias]['total_quantity']))
		{
			if(is_null($this->data[$this->alias]['total_quantity']) || $this->data[$this->alias]['total_quantity']=="")
			{
				$this->data[$this->alias]['total_quantity']=0;
			}
		}
		if($this->_isNew())
		{
			$this->data[$this->alias]['status'] = self::UNPUBLISH;
			$this->data[$this->alias]['purchase_link_status'] = self::PURCHASE_LINK_ON;
			/*
			if($this->data[$this->alias]['deal_type'] == self::TYPE_OFFER)
			{
				$this->data[$this->alias]['purchase_link_status'] = self::PURCHASE_LINK_ON;
			} else {
				if(isset($this->data[$this->alias]['purchase_link_status']) && $this->data[$this->alias]['purchase_link_status']!=self::PURCHASE_LINK_ON)
				{
					$this->data[$this->alias]['purchase_link_status'] = self::PURCHASE_LINK_OFF;
					$this->data[$this->alias]['code'] = $this->generateRandomUniqueValue("code");
				}
			}
			*/
		}
		//paid listing check - for new deals or for allowed active deals
		if(AppUtility::allowPaidListing())
		{
			if(($this->_isNew() || (isset($this->data[$this->alias]['status']) && $this->data[$this->alias]['status']==self::PUBLISH)))
			{
				if(!$this->isDealEnabledInPaidListing(@$this->data[$this->alias]['listing_id'], @$this->data[$this->alias]['id']))
				{
					return false;
				} else if($this->isActiveDealsLimitReached(@$this->data[$this->alias]['listing_id'], @$this->data[$this->alias]['id'])) {
					return false;
				}
			}
		}
		return parent::beforeSave($options);
	}
	
	function image($result)
	{
		$image = '/uploads/deal_image.gif';
		if(!empty($result)  &&  isset($result[$this->alias]['uploadedFile']) && !empty($result[$this->alias]['uploadedFile']))
		{
			$image = '/uploads/deal_assets/'.$result[$this->alias]['uploadedFile'];
		}
		return $image;
	}
	
	function viewUrl($result)
	{
		//$url = '/deals/deals/view/'.$result[$this->alias]['id'].'/'.$result[$this->alias]['deal_type'];
		$url = '/deals/deals/view/'.$result[$this->alias]['id'];
		return $url;
	}
	
	function isFutureDate($params, $dateFieldName)
	{
		$result = true;
		if(isset($params[$dateFieldName]))
		{
			$result = false;
			if(time() < (strtotime($params[$dateFieldName])+(24*60*60)-1))
			{
				$result = true;
			}
		}
		return $result;
	}

	
	function finalPrice($result)
	{
		$price = 0;
		if($result[$this->alias]['discount_type'] == self::DISCOUNT_TYPE_FLAT)
		{
			$price = number_format(($result[$this->alias]['regular_price'] - $result[$this->alias]['discount']),2,'.','');
		} else {
			$price = number_format((($result[$this->alias]['regular_price']/100)*(100 - $result[$this->alias]['discount'])),2,'.','');
		}
		return $price;
	}
	
	function isValidPercentage($params)
	{
		$return = true;
		if(isset($this->data[$this->alias]['discount_type']) && isset($this->data[$this->alias]['discount']))
		{
			if($this->data[$this->alias]['discount_type'] == self::DISCOUNT_TYPE_PERCENT)
			{
				if($this->data[$this->alias]['discount'] <= 100)
				{
					$return = true;
				} else {
					$return = false;
				}
			}
		}
		return $return;
	}
	
	function deal_status($result)
	{
		$dealStatus = "Inactive";
		if(time() > strtotime($result[$this->alias]['expires']))
		{
			$dealStatus = "Expired";
		} else if($result[$this->alias]['status'] == self::UNPUBLISH && time() < strtotime($result[$this->alias]['publish_on_date']." ".$result[$this->alias]['publish_on_time'])) {
			$dealStatus = "Unpublished";
		} else if($result[$this->alias]['status'] == self::UNPUBLISH && time() < strtotime($result[$this->alias]['expires'])) {
			$dealStatus = "Inactive";
		} else if($result[$this->alias]['status'] == self::PUBLISH) {
			$dealStatus = "Active";
		}
		return $dealStatus;
	}
	
	function isValidPublishDateTime($params)
	{
		$return = true;
		if(isset($this->data[$this->alias]['publish_on_date']))
		{
			$publishOnDateTime = $this->data[$this->alias]['publish_on_date'];
			if(isset($this->data[$this->alias]['publish_on_time']))
			{
				$publishTime = $this->data[$this->alias]['publish_on_time'];
				if(is_array($publishTime))
				{
					$publishTime = implode(":", $publishTime);
				}
				$publishOnDateTime .= " ".$publishTime;
			}
			if($this->compareDateTimeStrings($publishOnDateTime, date("Y-m-d H:i:s")) !== 1)
			{
				$return = false;
			}
		}
		return $return;
	}
	
	function isOlderThanPublishDateCheck($params)
	{
		$return = true;
		if(isset($this->data[$this->alias]['expires']) && isset($this->data[$this->alias]['publish_on_date']))
		{
			$publishOnDateTime = $this->data[$this->alias]['publish_on_date'];
			if(isset($this->data[$this->alias]['publish_on_time']))
			{
				$publishTime = $this->data[$this->alias]['publish_on_time'];
				if(is_array($publishTime))
				{
					$publishTime = implode(":", $publishTime);
				}
				$publishOnDateTime .= " ".$publishTime;
			}
			if($this->compareDateTimeStrings($this->data[$this->alias]['expires'], $publishOnDateTime) !== 1)
			{
				$return = false;
			}
		}
		return $return;
	}
	
	/*
	 * will convert datetime strings to datetime objects and return result after comparing them
	 * RESULT: -1 = datetime1 is smaller than datetime2
	 * RESULT: 0 = datetime1 is equals to datetime2
	 * RESULT: 1 = datetime1 is larger than datetime2
	 * RESULT: bool false : if datetime strings are not proper or any other error
	 */
	private function compareDateTimeStrings($datetime1, $datetime2)
	{
		$result = false;
		if(is_string($datetime1) && is_string($datetime2) && strlen(trim($datetime1)) && strlen(trim($datetime2)))
		{
			//$utcTimezone = new DateTimeZone("UTC");
			$datetime1 = new DateTime($datetime1);//, $utcTimezone
			$datetime2 = new DateTime($datetime2);//, $utcTimezone
			
			// doesn't work in php 5.2
			//$dtdiff = $datetime1->diff($datetime2);

			// php 5.2 workaround
			$datetime_one_string = $datetime1->format('U');
			$datetime_two_string = $datetime2->format('U');

			$difference = $datetime_one_string - $datetime_two_string;

			$result = 0;
			if($difference > 0)
			{
				$result = 1;
			} elseif($difference < 0) {
				$result = -1;
			}
		}
		return $result;
	}
	
	function afterInitialize()
	{
		$this->setFieldProperties('discount_type', array('options'=>array(self::DISCOUNT_TYPE_FLAT=>__("Flat"),self::DISCOUNT_TYPE_PERCENT=>__("Percentage"))));
		//$this->setFieldProperties('purchase_link_status', array('options'=>array(0=>__("No"),1=>__("Yes"))));
		$this->setFieldProperties('asset_inputs', array('addMoreLabel'=>__("Add more Images"),'label'=>__("Images"),));
		parent::afterInitialize();
	}
	
	function hasDefaultImage($id)
	{
		return $this->DealAsset->hasAny(array('is_default'=>1,'deal_id'=>$id));
	}
	
	function getDefaultFields()
	{
		$classVars = get_class_vars(__CLASS__);
		$fields =  array_keys($classVars['fieldProperties']);
		$fields = array_combine($fields,$fields);
		unset($fields['asset_inputs']);
		return array_values($fields);
	}
	
	function hasExpired($dealId)
	{
		//if deal is not active/publish then return true
		if($this->hasAny(array($this->alias.".id"=>$dealId,$this->alias.".status"=>self::UNPUBLISH)))
		{
			return true;
		}
		//if "expires" is NULL then return false (as deal will never expire as per date criteria)
		if($this->hasAny(array($this->alias.".id"=>$dealId,'OR'=>array(array($this->alias.".expires"=>NULL),array($this->alias.".expires"=>"0000-00-00")))))
		{
			return false;
		}
		//if "expires" is not NULL and is lesser than current(system) date then return false else true 
		if($this->hasAny(array($this->alias.".id"=>$dealId,"DATE(".$this->alias.".expires) >="=>date("Ymd"))))
		{
			return false;
		} else {
			return true;
		}
	}
	
	function canBePurchased($dealId, $quantity = 1)
	{
		$return = false;
		if(!$this->hasExpired($dealId))
		{
			/*
			$conditions = array(
					$this->alias.".id"=>$dealId,
					$this->alias.".purchase_link_status"=>1,
					"OR"=>array(
							array($this->alias.".total_quantity"=>0),
							array("(".$this->alias.".total_quantity - ".$this->alias.".quantity_consumed) >=" => $quantity)
							//array($this->alias.".total_quantity > ".$this->alias.".quantity_consumed")
					)
			);
			if($this->hasAny($conditions))
			{
				$return = true;
			}
			*/
			$deal = $this->findById($dealId);
			if($deal)
			{
				//if($deal[$this->alias]['purchase_link_status'])
				//{
					if($deal[$this->alias]['total_quantity'] == 0)
					{
						$return = true;
					} else {
						if(!$deal[$this->alias]['quantity_consumed'] && $deal[$this->alias]['total_quantity'] >= $quantity)
						{
							$return = true;
						} else if($deal[$this->alias]['quantity_consumed'] && (($deal[$this->alias]['total_quantity'] - $deal[$this->alias]['quantity_consumed']) >= $quantity)) {
							$return = true;
						}
					}
				//}
			}
		}
		return $return;
	}
	
	/*
	 * //as per ticket #5183 details, field to be used as city field = provincia
	 * //not the zona - which is mapped as city field in map config settings
	 */
	function getCitiesForNewsletter()
	{
		return array();
		
		$cityFieldProperties = cri("CustomField")->find("first",array("conditions"=>array("CustomField.name"=>"provincia")));
		return $cityFieldProperties['CustomField']["options"];
	}
	
	function getDealsForNewsletter($city,$limit = 100)
	{
		$deals = array();
		$conditions = array($this->alias.'.status'=>self::PUBLISH);
		$conditions[] = array(
			'OR'=>array(
				array($this->alias.".expires"=>NULL),
				array($this->alias.".expires"=>"0000-00-00"),
				array("DATE(".$this->alias.".expires) >="=>date("Ymd"))
			)
		);
		$order = array($this->alias.'.created'=>'DESC');
		$deals = $this->find('all',array('conditions'=>$conditions,'order'=>$order,'limit'=>$limit,'recursive'=>0));
		return $deals;
	}
	
	function getListingDeals($listingIds)
	{
		$deals = array();
		if($listingIds && $this->isDealEnabled())
		{
			if(!is_array($listingIds))
			{
				$listingIds = array($listingIds);
			}
			$conditions = array($this->alias.'.status'=>self::PUBLISH, $this->alias.'.listing_id'=>$listingIds);
			$conditions[] = array(
					'OR'=>array(
							array($this->alias.".expires"=>NULL),
							array($this->alias.".expires"=>"0000-00-00"),
							array("DATE(".$this->alias.".expires) >="=>date("Ymd"))
					)
			);
			$deals = $this->find('all',array('conditions'=>$conditions,'recursive'=>-1));
		}
		return $deals;
	}
	
	function autoDealPublish()
	{
		$conditions = array($this->alias.".status"=>self::UNPUBLISH, $this->alias.".activated"=>0);
		$conditions[] = array("DATE(".$this->alias.".expires) >" => date("Ymd"));
		$minuteMargin = cr("DealAutoFunctionMinuteMargin");
		if($minuteMargin)
		{
			$conditions[] = array(
					"DATE_SUB('".date("Y-m-d H:i:s")."', INTERVAL ".$minuteMargin." MINUTE ) <= CONCAT(Deal.publish_on_date,' ',Deal.publish_on_time)",
					"'".date("Y-m-d H:i:s")."' >= CONCAT(Deal.publish_on_date,' ',Deal.publish_on_time)"
			);
		} else {
			$conditions[] = array(
					"DATE(".$this->alias.".publish_on_date) = DATE('".date("Y-m-d")."')",
					"TIME_FORMAT(".$this->alias.".publish_on_time, \"%H:%i\") = TIME_FORMAT('".date("Y-m-d H:i:s")."',\"%H:%i\")",
			);
		}
		//$this->updateAll(array($this->alias.".status" => self::PUBLISH),$conditions);
		$dealIds = $this->find('list',array('conditions'=>$conditions, 'fields'=>array('id'),'recursive'=>-1));
		if(!empty($dealIds))
		{
			foreach($dealIds as $dealId)
			{
				$this->activateDeal($dealId);
			}
		}
	}
	
	function autoDealUnpublish()
	{
		$conditions = array($this->alias.".status"=>self::PUBLISH);
		$conditions[] = array("DATE(".$this->alias.".expires) <" => date("Y-m-d"));
		//$this->updateAll(array($this->alias.".status" => self::UNPUBLISH),$conditions);
		$dealIds = $this->find('list',array('conditions'=>$conditions, 'fields'=>array('id'),'recursive'=>-1));
		if(!empty($dealIds))
		{
			foreach($dealIds as $dealId)
			{
				$this->deactivateDeal($dealId);
			}
		}
	}
	
	function activateDeal($dealId)
	{
		$this->id = $dealId;
		if($this->saveField('status',self::PUBLISH))
		{
			if($this->hasAny(array($this->alias.".id"=>$dealId, $this->alias.".activated"=>0)))
			{
				$this->id = $dealId;
				$this->saveField('activated',1, false, false);
			}
			return true;
		}
		return false;
	}
	
	function deactivateDeal($dealId)
	{
		$this->id = $dealId;
		if($this->saveField('status',self::UNPUBLISH))
		{
			if($this->hasAny(array($this->alias.".id"=>$dealId, $this->alias.".activated"=>0)))
			{
				$this->id = $dealId;
				$this->saveField('activated',1, false, false);
			}
			return true;
		}
		return false;
	}
	
	function isDealEnabled()
	{
		return ((cr("DealConfig.enable_deals"))?true:false);
	}
	
	function isDealEnabledInPaidListing($listingId = null, $dealId = null)
	{
		$result = true;
		if(AppUtility::allowPaidListing())
		{ 
			if($dealId && !$listingId)
			{
				$listingId = $this->field("listing_id",array($this->alias.'.id' => $dealId));
			}
			if($listingId)
			{
				$EffectivePlan = cri("PaidListings.ListingPlan")->getEffectivePlan($listingId);
				$result = $EffectivePlan->isDealEnabled();
			}
		}
		return $result;
	}
	
	function isActiveDealsLimitReached($listingId = null, $dealId = null)
	{
		$result = false;
		if(AppUtility::allowPaidListing())
		{
			if($dealId && !$listingId)
			{
				$listingId = $this->field("listing_id",array($this->alias.'.id' => $dealId));
			}
			if($listingId)
			{
				$EffectivePlan = cri("PaidListings.ListingPlan")->getEffectivePlan($listingId);
				$allowedActiveDealsCount = $EffectivePlan->getAllowedTotalDealsCount();
				if(is_null($allowedActiveDealsCount))	//for case reported in ticket 6886 - as no plan exists/applied
				{
					return false;
				}
				$activeDealsCount = $this->find('count',array('conditions'=>array($this->alias.".listing_id" => $listingId, $this->alias.".status" => self::PUBLISH),'recursive'=>-1));
				if($allowedActiveDealsCount <= $activeDealsCount)
				{
					$result = true;
				}
			}
		}
		return $result;
	}
	
	function setDealCategoryOptions()
	{
		$categories = $this->ListCategory->find('list',array('conditions'=>array('ListCategory.parent_id'=>null),'recursive'=>-1));
		$this->setFieldProperties('list_category_id',array('options'=>$categories));
	}
	
	function getUserPostedDeals($userId)
	{
		$deals = array();
		if($userId)
		{
			$deals = $this->find('all',array('conditions'=>array($this->alias.'.user_id' => $userId),'recursive'=>-1));
		}
		return $deals;
	}
	
	function getDiscountTypes()
	{
		return array(
				self::DISCOUNT_TYPE_FLAT => __("Flat"),
				self::DISCOUNT_TYPE_PERCENT => __("Percentage")
		);
	}
	
}
?>